What you wanted to do seems like folding or un-folding of a sequence of objects of the same type. It is tempting to use
apply for this purpose, because in many cases it will indeed work. But it's not exactly the right tool for this, and here is why:
apply is a meta-programming mechanism, not only that, it is also too general for the task because it can handle sequences of objects of different types, not necessarily calling functions of two arguments. As a consequence, some times you will get an incorrect behaviour, for example:
(apply 'concat "baz" '("foo" "bar"))
But intuitively, you'd expect a type mismatch here.
There is no way to ensure
apply will be able to process as many arguments as you can give it, it's typically a limit imposed by the language implementation.
The function called by
apply will be able to get a reference of the arguments list passed to it in this way. This is also not obvious, and may lead to errors later:
(let ((test (list 1 2 3)))
(apply (lambda (&rest x)
(prog1 (cl-reduce '+ x) (setcar x 0)))
;; This behaviour is undefined. Could end up both ways
> (6 1 2 3)
> (6 0 2 3)
If the arguments list is copied, then you pay the price of consing more memory than needed, but if it's not copied (passed as is), then you risk spoiling the list, if the function being called modifies it.
So, the better way of doing it is to use
cl-reduce. The benefit is that it was specifically designed to do this kind of tasks.
(cl-reduce 'concat '("foo" "bar" "baz"))