It seems that apply: calls the typeclass solver on the goal it produces and somehow accepts a partial solution from elpi's typeclass solver. I am surprised both by the fact that the typeclass solver gives a partial answer and that apply: accepts it.
From Corelib Require Import ssreflect.
Class A := {}.
Goal (nat -> A) -> A.
Proof.
move=> hyp.
apply: id.
(* Goal : A *)
Abort.
From elpi Require Import tc.
Class B := {}.
Goal (nat -> B) -> B.
Proof.
move=> hyp.
apply: id.
(* Goal : nat *)
Abort.
Also, if I replace B by A in the last Goal, the apply: id command fails, which is even weirder.
Goal (nat -> A) -> A.
Proof.
move=> hyp.
Fail apply: id.