This should be considered an addendum to the other answers here.
Consider the following timings
identitiesImplicit = ConstantArray[# &, 10000];
First /@
{
Timing[Compose[##, Pi] & @@ identitiesImplicit],
Timing[(Composition @@ identitiesImplicit)[Pi]],
Timing[Fold[#2[#1] &, Pi, identitiesImplicit]],
Timing[Last[ComposeList[identitiesImplicit, Pi]]]
}
-> {0.014458, 0.012889, 0.008957, 0.004041}
My explanations: Fold and ComposeList prevent copying of the data. ComposeList and Fold handle the stack nicely, whereas Compose and Composition do not. The fact that ComposeList stores values intermediately takes hardly any time at all (compare CompoundExpression with Last[List[##]]& for large sets of instructions). As ComposeList is an internal function that does exactly what it should except only for intermediate storing that takes little time, it performs best.
Copying the data does take a little time, as well as precious memory of course, as can be observed by comparing the results of the code below by that above. It is not very noticable, but this is not the most extreme example. In what is below, no coping of the long list of functions occurs.
iIS = Sequence @@ identitiesImplicit;
First /@
{
Timing[Compose[iIS, Pi]],
Timing[Composition[iIS][Pi]],
Timing[Fold[#2[#1] &, Pi, {iIS}]],
Timing[Last[ComposeList[{iIS}, Pi]]]
}
-> {0.011800, 0.011225, 0.008991, 0.004181}
Of course, it is not very feasible to pass around Sequences just to avoid this kind of copying of data, so Fold and Composition have an advantage here.
To see what I mean by "does not copy the data", consider the following
{
Clear[identitiesImplicit, iIS];
MemoryInUse[],
identitiesImplicit = ConstantArray[# &, 100000];
MemoryInUse[],
iIS = Sequence @@ identitiesImplicit;
MemoryInUse[],
aaa = {iIS};
"no memory increase",
MemoryInUse[]
}
-> {44769848, 45570024, 46370120, "no memory increase", 46370024}