Cache target table template tuple and its schema in insert executor, to ...

...avoid serializing default values on every insert.
p_init is really an extension of the constructor, so it's a little misleading to have guards like this. 
Instead, you could assert that the member is null assuming you initialized it in the constructor.
BTW, I think the precedent (and I don't know how I feel about this) is to mostly ignore member initialization in the constructor and just assume that p_init is called once immediately thereafter to patch things up.
The rationale for having a p_init function at all vs. more complete constructors is a little bit lost to history.
I THINK the rationale was to allow Executor constructors to run in any order while maintaining the constraint that p_init is called AFTER the parent-child connections have been established AND called in child-first order.
That way, for example, a parent executor p_init can access the output temp table defined by the child executor p_init. 
I haven't done the research to determine whether there is any advantage to being able to run executor constructors in some other order and/or prior to linking up the parent/child relationships. 

I've got a longer-term hope/fantasy to unify the PlanNode and Executor trees.
In that world, being able to construct the hybrid PlanNode/Executor objects in a deserialization order different from child-first and/or allowing the parent/child relationships to be initialized (as they are now) in a separate pass AFTER PlanNode construction MIGHT become useful if it is not already. 
OR maybe PlanNode serialization/deserialization could be reworked more like Expression serialization/deserialization as a child-first bottom-up process.