Loop over groupby object
When you groupby a DataFrame/Series, you create a pandas.core.groupby.generic.DataFrameGroupBy object which defines the __iter__() method, so can be iterated over like any other objects that define this method. It can be cast into a list/tuple/iterator etc. In each iteration, it returns a tuple whose first element is the grouper key and the second element is a dataframe created by the grouping; you can think of it like iteration over dict_items where in each iteration, the items are key-value tuples. Unless you select a column or columns on the groupby object, it returns all columns of the dataframe. The output of the following code illustrates this point.
import pandas as pd
from IPython.display import display
df = pd.DataFrame({
'A': ['g1', 'g1', 'g2', 'g1'],
'B': [1, 2, 3, 4],
'C': ['a', 'b', 'c', 'd']
})
grouped = df.groupby('A')
list(grouped) # OK
dict(iter(grouped)) # OK
for x in grouped:
print(f" Type of x: {type(x).__name__}\n Length of x: {len(x)}")
print(f"Value of x[0]: {x[0]}\n Type of x[1]: {type(x[1]).__name__}")
display(x[1])

A pretty useful use case of a loop over groupby object is to split a dataframe into separate files. For example, the following creates two csv files (g_0.csv and g_1.csv) from a single dataframe.
for i, (k, g) in enumerate(df.groupby('A')):
g.to_csv(f"g_{i}.csv")
Loop over grouped dataframe
As mentioned above, groupby object splits a dataframe into dataframes by a key. So you can loop over each grouped dataframe like any other dataframe. See this answer for a comprehensive ways to iterate over a dataframe. The most performant way is probably itertuples(). Following is an example where a nested dictionary is created using a loop on the grouped dataframe:
out = {}
for k, g in grouped: # loop over groupby
out[k] = {}
for row in g.itertuples(): # loop over dataframe
out[k][row.B] = row.C
print(out)
# {'g1': {1: 'a', 2: 'b', 4: 'd'}, 'g2': {3: 'c'}}