I will try explaining it by showing you 1st iteration of the first loop.
for word in ['ox', 'cat', 'lion', 'tiger', 'bobcat']:
word variable will be a string, respectively 'ox', 'cat', 'lion', 'tiger' and 'bobcat' in each passing of this loop
for i in range(2, 7):
i variable will be respectively 2, 3, 4, 5 and 6 on each of the next passings of the loop. Range function always means a range of <2, 7) in mathematical notation. That's why i won't be equal 7.
letters = len(word)
This doesn't need to be in the 2nd loop (and tbh woud be better before the loop). It just makes so letters variable is equal to the length of the word variable, so if word = 'ox' then letters = 2, if word = 'lion' then letters = 4.
if (letters % i) == 0:
To understand this you need to understand modulo operator represented by %. Basically it means rest of the division. Few examples:
5 % 2 = 1
4 % 2 = 0
10 % 6 = 4
23 % 9 = 5
30 % 30 = 0
With that in mind this line of code take the letters variable (which is length of the word variable as mentioned earlier) and tries to divide it by current i value (which can be 2, 3, 4, 5 or 6) and if it can be divided with the rest equal to 0 then it prints out the divider and the word.
Below is an extra rundown of each of the outputs describing internal values of the program. In each of these cases letters % i equals to 0 of course.
2 ox # letters = 2, because word = 'ox', also i = 2
3 cat # letters = 3, because word = 'cat', also i = 3
2 lion # letters = 4, because word = 'lion', also i = 2
4 lion # letters = 4, because word = 'lion', also i = 4
5 tiger # letters = 5, because word = 'tiger', also i = 5
2 bobcat # letters = 6, because word = 'bobcat', also i = 2
3 bobcat # letters = 6, because word = 'bobcat', also i = 3
6 bobcat # letters = 6, because word = 'bobcat', also i = 6