rx-to-string takes a regexp form as an argument. The syntax is the same as the argument of rx.
(rx-to-string '(or "foo" "bar"))
"\\(?:\\(?:bar\\|foo\\)\\)"
What you tried passing is not a regexp form, but a list of regexp forms. Since what you mean is the sequence of regular expressions symbol-start followed by one of a bunch of strings followed by symbol-end, you need to lead with the sequence operator sequence (which can be abbreviated to seq or :, or weirdly even and).
(rx-to-string `(: symbol-start (or ,@strings) symbol-end))
"\\(?:\\_<\\(?:ba[rz]\\|foo\\)\\_>\\)"
rx is in fact a tiny wrapper around rx-to-string that operates at compile time because it's a macro. What makes this confusing is that if you pass multiple arguments to rx, there is an implicit sequence operator. The documentation of rx could stand to be clarified.
(rx (: symbol-start (or "foo" "bar" "baz") symbol-end))
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
(rx symbol-start (or "foo" "bar" "baz") symbol-end)
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"