Are you really sure you wish to check for control sequence tokens?
Primitives like \relax are not macros but they are control sequences.
Active characters (character tokens of category code 13) are not control sequence tokens but they can be defined to be macros.
A control sequence token or an active character token whose meaning denotes that it is undefined also is not a macro.
The case of the argument in question being empty also is a case where no macro/no control sequence token is present.
Arguments starting with opening curly braces /catcode-1-characters might require special attention.
The following code provides testing by checking the meaning of the first token of the argument in question in case that argument is not empty.
Leading space tokens and leading catcode-1-characters are taken into account.
%%===============================================================
%% \firstoftwo and \secondoftwo:
%%...............................................................
\long\def\firstoftwo#1#2{#1} \long\def\secondoftwo#1#2{#2}
%%---------------------------------------------------------------
%% \AtIfArgsFirstTokenIsMacro - takes three macro-arguments and
%% forks depending on whether the first argument
%% holds a first/leading token whose \meaning equals
%% one of the phrases "macro:", "\long macro:".
%% If so delivers the second argument, otherwise
%% delivers the third argument.
%%
%% The macro is suitable for expansion contexts
%% and due to \romannumeral-expansion delivers the
%% result after two expansion steps/after "being
%% hit by two \expandafter-chains".
%%
%% The case of the first argument being empty/not
%% holding any token at all is considered a case
%% where the argument does not hold a first/leading
%% token at all and thus does not hold a first/leading
%% token whose meaning equals one of the phrases
%% "macro:", "\long macro:".
%%
%% The test does not rely on some token being
%% undefined. eTeX- or whatsoever extensions are not
%% required.
%%
%% I assume there is room for improvement/shortening
%% the code.
%%
%% Testing by means of macros for a leading
%% \outer-macro-token in the argument is somehat
%% obsolete and impossible as \outer-tokens cannot
%% occur inside macro-arguments.
%%
%%...............................................................
\def\AtIfArgsFirstTokenIsMacro#1#2{%
\long\def\AtIfArgsFirstTokenIsMacro##1##2##3{%
\romannumeral\iffalse{\fi\expandafter\secondoftwo\expandafter
{\expandafter{\string##1}\expandafter\expandafter\expandafter
\firstoftwo\expandafter\expandafter\expandafter\firstoftwo
\expandafter\secondoftwo\expandafter{\expandafter{\iffalse}}\fi
\expandafter\secondoftwo\string}\expandafter\firstoftwo
\expandafter{\iffalse}\fi\iffalse{\fi
\expandafter\innerAtIfArgsFirstTokenIsMacro\meaning##1#1}{}%
{%
\iffalse{\fi
\expandafter\innerAtIfArgsFirstTokenIsLong\meaning##1#2 #1}{}%
}{\secondoftwo}%
}{\firstoftwo}%
{0 ##3}{0 ##2}%
}%
\long\def\innerAtIfArgsFirstTokenIsMacro##1#1{%
\innerAtIfArgsFirstTokenIs{##1}%
}%
\long\def\innerAtIfArgsFirstTokenIsLong##1#2 #1{%
\innerAtIfArgsFirstTokenIs{##1}%
}%
\long\def\innerAtIfArgsFirstTokenIs##1{%
\iffalse{\fi\expandafter\secondoftwo\expandafter{\string##1}%
\expandafter\firstoftwo\expandafter{\iffalse}\fi\expandafter
\expandafter\expandafter\firstoftwo}{\expandafter\expandafter
\expandafter\secondoftwo}\expandafter\secondoftwo\expandafter
{\iffalse}\fi
}%
}%
% Somehow get the catcode-12-token-phrases "macro:" and "\long"
% as argument of \AtIfArgsFirstTokenIsMacro - hereby
% it is relied on the usual catcode settings and on primitives not
% being redefined and on integer parameters like \globaldefs and
% \endlinechar and \escapechar holding usual values, thus:
\begingroup
\edef\AtIfArgsFirstTokenIsMacro{%
{\string m\string a\string c\string r\string o%
\string :}{\string\long}%
}%
\expandafter\endgroup%
\expandafter\AtIfArgsFirstTokenIsMacro%
\AtIfArgsFirstTokenIsMacro%
%%===============================================================
\def\test{defined}
\long\def\testb{defined}
\catcode`\Z=13
1 \AtIfArgsFirstTokenIsMacro{\UndFINeD}{Macro}{Not Macro} % OK
2 \AtIfArgsFirstTokenIsMacro{\undefined A}{Macro}{Not Macro} % OK
3 \AtIfArgsFirstTokenIsMacro{\undefined A\fi}{Macro}{Not Macro} % OK
4 \AtIfArgsFirstTokenIsMacro{}{Macro}{Not Macro} % OK
5 \AtIfArgsFirstTokenIsMacro{Z}{Macro}{Not Macro} % OK
6 \AtIfArgsFirstTokenIsMacro{\relax}{Macro}{Not Macro} % OK
7 \AtIfArgsFirstTokenIsMacro{\TeX}{Macro}{Not Macro} % OK
8 \AtIfArgsFirstTokenIsMacro{\test}{Macro}{Not Macro} % OK
9 \AtIfArgsFirstTokenIsMacro{\par}{Macro}{Not Macro} % Evaluate/OK
10 \AtIfArgsFirstTokenIsMacro{\fi}{Macro}{Not Macro} % OK
11 \AtIfArgsFirstTokenIsMacro{\else}{Macro}{Not Macro} % OK
12 \AtIfArgsFirstTokenIsMacro{\if}{Macro}{Not Macro} % OK
13 \AtIfArgsFirstTokenIsMacro{#}{Macro}{Not Macro} % OK
14 \AtIfArgsFirstTokenIsMacro{ }{Macro}{Not Macro} % OK
15 \AtIfArgsFirstTokenIsMacro{\endcsname}{Macro}{Not Macro} % OK
16 \AtIfArgsFirstTokenIsMacro{\AtIfArgsFirstTokenIsMacro}{Macro}{Not Macro} %Long Macro
17 \AtIfArgsFirstTokenIsMacro{\bgroup}{Macro}{Not Macro}% OK
18 \AtIfArgsFirstTokenIsMacro{\egroup}{Macro}{Not Macro}% OK
\letZ=\relax
19 \AtIfArgsFirstTokenIsMacro{Z}{Macro}{Not Macro}% OK
20 \AtIfArgsFirstTokenIsMacro{\testb}{Macro}{Not Macro}% OK
21 \AtIfArgsFirstTokenIsMacro{\testb bla bla}{Macro}{Not Macro}% OK
22 \AtIfArgsFirstTokenIsMacro{bla \fi}{Macro}{Not Macro}% OK
23 \AtIfArgsFirstTokenIsMacro{several tokens}{Macro}{Not Macro}% OK
24 \AtIfArgsFirstTokenIsMacro{A}{Macro}{Not Macro}% OK
25 \AtIfArgsFirstTokenIsMacro{{\undefined A}\fi}{Macro}{Not Macro}% OK
26 \csname\AtIfArgsFirstTokenIsMacro{\tEx}{tEx}{TeX}\endcsname% OK
27 \if0\AtIfArgsFirstTokenIsMacro{\tEx}{0}{1}\tEx \else \TeX\fi% OK
\bye
\noexpandbefore\relax(assuming nobody is redefinining\relax); the test is good for one token arguments, but does not catch active characters as being macros, which may not be what you want. It also doesn't catch control sequences\letto a character. – egreg May 01 '16 at 19:59\stringify the token and then check if the expansion begins with\escapechar? – GuM May 01 '16 at 21:21