The return value of the nosklo chunker function is called a generator, an object that will generate values when being iterated. In this case the generator is created using a generator expression, an indivisible piece of code between the parentheses: (seq[pos:pos + size] for pos in xrange(0, len(seq), size)).
>>> def chunker(seq, size):
...     return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
... 
>>> result = chunker([1, 2, 3], 2)
>>> print(result)
<generator object <genexpr> at 0x10581e1e0>
>>> next(result)
[1, 2]
>>> next(result)
[3]
Regarding what gets called, we can rewrite the loop code like this to see it better:
>>> generator = chunker(animals, 3)
>>> for chunk in generator:
...     print chunk
... 
['cat', 'dog', 'rabbit']
['duck', 'bird', 'cow']
['gnu', 'fish']    
The chunker functions gets called only once and returns the generator object, which we store in the generator variable. The for loop then only works with this generator object and calls it 3 times.
To be able to print the actual calls of this generator, you would have to include the print statement inside the generator expression (seq[pos:pos + size] for pos in xrange(0, len(seq), size)), which is not allowed. But we can rewrite this generator expression to a normal generator function using the yield statement, a more verbose but also more versatile form of generator where we can include the print statement and which will work as you expected initially:
>>> def chunker2(seq, size):
...     for pos in xrange(0, len(seq), size):
...         print('chunker2 generator called')
...         yield seq[pos:pos + size]
... 
>>> for group in chunker2(animals, 3):
...     print group
... 
chunker2 generator called
['cat', 'dog', 'rabbit']
chunker2 generator called
['duck', 'bird', 'cow']
chunker2 generator called
['gnu', 'fish']
Here the chunker2 function itself is the actual generator and gets called 3 times.