Emacs is a “Lisp-2” where the "2" means that function names and variable names are in two distinct name-spaces, and hence there can be both a function and a variable with any given name foo.
A function definition (defun foo …) and a function call (foo …) use the function slot of the symbol foo. A variable assignment (setq foo …), a variable binding (let ((foo …)) …), and a variable reference x use the value slot of the symbol foo.
A consequence is that we need more than just the syntax (foo …) for calling functions, as we need to distinguish between calling the function named foo, and evaluating the variable foo to a function value and calling that.
In Emacs Lisp (foo …) only ever calls the function by that name. To call a function which is stored in the value slot of a symbol (i.e. a variable), use funcall.
(funcall fn x)
More generally, but infrequently, the argument to funcall can be any Lisp expression.
(funcall (car flist) 1 3)
funcall is an ordinary function, so its arguments are evaluated before the call happens (in these examples meaning that fn and (car flist) are each evaluated to their function values).
Note also that the error invalid function (caar flist) was not saying that (caar flist) doesn't evaluate to a function, but rather that the form (caar flist) itself is not a function (it's a list of two symbols).
Lisp functions take a list of arguments. Sometimes, in addition to calling a variable function, you need to call the function with a variable list of arguments. In this case, use apply instead of funcall. The last argument to apply is used as a list of remaining arguments.
In this particular case, where the code of the function is fully known, you can also use cl-flet from the CL library that is distributed with Emacs. This doesn't let you easily pass the function around, which may or may not be an issue in your real program.
(require 'cl-lib)
(let ((lexical-binding t)
(x 4))
(cl-flet ((fn (y) (+ y 4)))
(pcase x
(10 (- x 2))
(4 (fn x)))))
letbinds variables, not functions. Sofnis a variable whose value is a function. You need to call it as(funcall fn x).