The return value of your iterator function is used as the argument to the StopIteration that it raises when it terminates:
>>> it = gen_test()
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
4
>>> next(it)
5
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: [0, 1, 2, 3, 4, 5]
Only the first StopIteration gets the specified value. Further attempts to iterate an empty generator will raise an empty exception:
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
You can extract the return value from a normal run of the iterator by avoiding for loops and trapping the exception yourself:
it = gen_test()
while True:
    try:
        x = next(it)
        # Do the stuff you would normally do in a for loop here
    except StopIteration as e:
        ret = e.value
        break
print(ret)
All this is an awkward approach given that you have to decide between not using for loops and not being able to return your accumulated data. Assuming that you're not OK with trying to accumulate the data externally (e.g. just doing list(gen_test())), you can make your generator's state publicly accessible by using a class:
class gen_test:
    def __init__(self):
        self.l = []
        self.it = iter(range(6))
    def __iter__(self):
        return self
    def __next__(self):
        i = next(self.it)
        self.l.append(i)
        return i
Now you can do something like
>>> it = gen_test()
>>> for x in it:
...     print(x)
0
1
2
3
4
5
>>> print(it.l)
[0, 1, 2, 3, 4, 5]