Understanding joined set-returning functions in the FROM list
The piece that you are missing is, that this is not a regular cross join, but a "LATERAL" cross join. 

So the fully written equivalent is: 

SELECT *
FROM my_table
   CROSS JOIN LATERAL unnest(my_col);


The keyword LATERAL is implicitly assumed if the join is done against a set returning function that's why cross join unnest(my_col) or even from my_table, unnest(my_col) works as well.

The LATERAL will change the cross join such that it takes one row from my_table and does a cross join of that (one) row with all rows returned from the set returning function. Then it does the same with the next row and so on. 

So it generates the cross join between the row containing array {a,b} and all its elements. And then another cross join with the row containing the array {c,d,e} and all its elements. 

The manual explains it this way:


  When a FROM item contains LATERAL cross-references, evaluation proceeds as follows: for each row of the FROM item providing the cross-referenced column(s), or set of rows of multiple FROM items providing the columns, the LATERAL item is evaluated using that row or row set's values of the columns. The resulting row(s) are joined as usual with the rows they were computed from. This is repeated for each row or set of rows from the column source table(s)