You can't pass table names as bind variables. And you can't have a forall statement that dynamically generates SQL statements, so each pass affects a different table.
So you need to stick with your original loop approach and forget forall:
for i in 1 .. p_tab.count
loop
dbms_output.put_line ( p_tab ( i ) ) ;
end loop;
Or, even better, ditch dynamic SQL and place the update statements directly in your code!