निरंजन
Look at the following comparison:
```
% arara: pdflatex
% arara: pdflatex
% arara: clean: { extensions: [ aux,log ] }
\documentclass{article}
\ExplSyntaxOn
\keys_define:nn { foo } {
foo .skip_gset:N = { \fooskip },
bar .tl_gset:N = { \barskip }
}
\cs_new:Npn \setkeys #1 {
\keys_set:nn { foo } { #1 }
}
\ExplSyntaxOff
\begin{document}
\setlength{\parindent}{0pt}
\setkeys{%
foo = {1in},%
bar = {1in}%
}
\subsubsection*{Unstretched}
\verb|\fooskip|: a\hskip\fooskip\relax b
\verb|\barskip|: a\hskip\barskip\relax b
\subsubsection*{Positive glue added}
\setkeys{%
foo = {1in plus 0.5in minus 0.1in},%
bar = {1in plus 0.5in minus 0.1in}%
}
\verb|\fooskip|: a\hskip\fooskip\relax b abcdefghi abcdefghi
abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
\verb|\barskip|: a\hskip\barskip\relax b abcdefghi abcdefghi
abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
\subsubsection*{Negative glue added}
\setkeys{%
foo = {1in plus 0.1in minus 0.5in},%
bar = {1in plus 0.1in minus 0.5in}%
}
\verb|\fooskip|: a\hskip\fooskip\relax b abcdefghi abcdefghi
abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
\verb|\barskip|: a\hskip\barskip\relax b abcdefghi abcdefghi
abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
\end{document}
```

Top Answer
Skillmon
The point of evaluation is different. With `.tl_(g)set:N` you store your literal input and whenever you use `\skip_horizontal:n` the stored input is evaluated to a skip and applied. However if you use `.skip_(g)set:N` the input is evaluated to a skip directly when you use the key, not when you use the value in `\skip_horizontal:N`.
There are different scenarios when the two make a difference. The first is if you use any of the font dependent units/sizes like `ex` and `em` and use the skips in contexts with changed font (size). The other scenario is if you use any of the context dependent lengths, like `\linewidth` or similar.
An MWE showing the different results of the two in such contexts:
```
\documentclass{article}
\ExplSyntaxOn
\keys_define:nn { my }
{
foo .tl_set:N = \l_my_foo_tl
,bar .skip_set:N = \l_my_bar_skip
}
\NewDocumentCommand \mysetup { m } { \keys_set:nn { my } {#1} }
\NewDocumentCommand \tlskip {} { \skip_horizontal:n { \l_my_foo_tl } }
\NewDocumentCommand \skipskip {} { \skip_horizontal:N \l_my_bar_skip }
\NewDocumentCommand \setboth { m } { \mysetup { foo = {#1}, bar = {#1} } }
\ExplSyntaxOff
\newcommand\test{A\tlskip B (tl)\par A\skipskip B (skip)\par}
\begin{document}
\setboth{.2\linewidth}
\begin{minipage}{.5\linewidth}
\test
\end{minipage}
\bigskip
\setboth{2em}
{%
\footnotesize
\test
}
\end{document}
```

These examples are both without glue, but the same applies with glue as well.
Another difference (that also directly follows) is the error messages becoming easier to comprehend because the reported line is closer to where the error was made if you input an invalid skip, for instance try what happens if you use `\setboth{5blubbs}` in above's examples.