2 примера: генератор списка и yield — разницы не видно. Некорректные примеры?
В добавок к ответу Pavel Denisov вброшу такой вариант:def forever(lst):
    while True:
        for item in lst:
            yield item
Будет йелдить бесконечно элементы списка, если список закончится - заново. Генератором генератора (generator comprehension) такого не добьёшься. В общем, generator comprehension - это как лямбды. Сокращённая запись для удобства, ведь намного удобнее и нагляднее написать','.join(str(x) for x in lst)
Чемdef str_gen(lst):
    for item in lst:
        yield str(item)

','.join(str_get(lst))
Хотя, суть одна.
Но некоторые вещи обычным generator comprehension не реализовать.
P.S. Генератор списков создаёт список. Это вот так: [x**2 for x in range(5)]
Вот пример генератора через функцию>>> def g():
...     while True:
...         yield 'a'
...         yield 'b'
...         yield 'c'
... 
>>> list(zip(g(), range(10)))
[('a', 0), ('b', 1), ('c', 2), ('a', 3), ('b', 4), ('c', 5), ('a', 6), ('b', 7), ('c', 8), ('a', 9)]
>>>
Функция даёт больше возможностей для формирования более гибких генераторов.