A string is an iterable because the str class/type implements the __iter__ method. By implementing the __iter__ method, the for-loop is able to iterate all members in the string. Whenever the for-loop asks for the next element in the string, Python's str class's iterable returns it's string instance's next character. As a result, i, in the context of the for-loop, is always the next character in the string.
Within the loop, list_ += i class works because Python's list class/type implements the __iadd__ method. __iadd__ is a method that is called whenever Python encounters the += operator. Normally, the __iadd__ operation of list is used to add elements from one iterable to the end of a list instance. Because the method is meant to combine iterables, you would receive a TypeError: 'int' object is not iterable if your code was the following:
list_ = []
string = '12345'
for i in string:
list_ += int(i)
print(list_)
However, your code works because, going back to the first discussion point, in Python, strings are iterables. As a result, it is perfectly legal in Python to say:
l=[]
s='omg'
l+=s
print(l)
# Output: ['o', 'm', 'g']
You might think your case is different than my example above because your case is looping over each character in the string rather than working with the string itself. However, Python does not have a character type, so effectively, every character (i) is a single-character string. As a result, every individual character i in your for-loop has its own __iter__ method, effectively allowing the character to be appended to the end of list_, as if the operation said: list += [i].