This is not entirely correct. While it’s true that "GF" by default has the "normal" class, it’s not what is responsible for the spacing. Any single-letter variable (like p or theta) also has the "normal" class. It is only because "GF" is in a string (with quotes), that it’s sensitive to spaces around it. The same is true for other elements which create a new frame, e.g. box or block.
For more detail, see the is_spaced function in the compiler’s source code.
A space is then only kept if at least one of the elements around it is spaced. One (slightly hacky) workaround to remove the “spacedness” of an element, while keeping it of class "normal", is by doing something like
#let symbol = math.class("normal", "GF" + h(0pt))
$ a symbol b $
![]()
See also this comment on GitHub.
(For this case, you should follow what @quachpas suggested though, as that is exactly what the op function is for.)