is intended to produce an iterator for the source data (a list of (word,list-of-words) pairs). There can be many reasons for this,
particularly if this gets handed to something which iterates and the
source data are not originally iterable (though a list is iterable).
Anyway, that step produces an iterator for use elsewhere.
The interactive code you cite illustrates the iterator protocol, which
is that calling next(it) on some iterator iteither produces the
next value from the iterator or raises StopIteration to indicate
that the iterator is now empty. All iterators behave this way.
When you iterate over some using, say, a for-loop, the mechanism of the
for-loop handles this behaviour for you.
I had a quick look at the code you cite. It looks like the author makes a new_words iterator, then replaces it with another iterator depending on what goes on, which presumably iterates through the problem solution space looking for matches, where new_words is an iterable producing potential matches to try at the current stage of the search.